<?php

require_once( 'flexical/model/feed.php' );
require_once( 'flexical/model/query.php' );
require_once( 'flexical/model/event.php' );

require_once( 'flexical/service/cao.php' );
require_once( 'flexical/service/cao-exception.php' );

/**
 * This hybrid CAO implementation uses the Zend Framework to download the list of Google Calendar feeds
 * and the SimplePie framework to download the events.
 */
class Flexical_Service_CAO_Hybrid extends Flexical_Service_CAO
{
	/**
	 * Uses Zend
	 */
	public function read_feeds( $username, $password )
	{
		$this->load_zend_framework();

		$service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;

		try
		{
			$client = Zend_Gdata_ClientLogin::getHttpClient( $username, $password, $service );
		}

		catch ( Exception $e )
		{
			throw new Flexical_Service_CAO_Exception( 'Error logging into Google Calendar', 0, $e );
		}

		$connection = new Zend_Gdata_Calendar( $client );

		try
		{
			$calendar_list_feed = $connection->getCalendarListFeed();
		}

		catch ( Exception $e )
		{
			throw new Flexical_Service_CAO_Exception( 'Error reading list of calendars', 0, $e );
		}

		$feeds = array();

		foreach ( $calendar_list_feed as $cal )
		{
			if ( $cal->title->text == null || $cal->title->text == '' )
			{
				continue;
			}

			$feed = $this->build_feed( $cal );
			$feeds[ $feed->url ] = $feed;
		}

		return $feeds;
	}

	private function load_zend_framework()
	{
		if ( ! class_exists( 'Zend_Loader' ) )
		{
			require_once( 'Zend/Loader.php' );
			Zend_Loader::loadClass('Zend_Gdata');
			Zend_Loader::loadClass('Zend_Gdata_AuthSub');
			Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
			Zend_Loader::loadClass('Zend_Gdata_Calendar');
			Zend_Loader::loadClass('Zend_Gdata_Calendar_EventQuery');
		}
	}

	private function build_feed( $cal )
	{
		$feed = new Flexical_Model_Feed();

		$feed->title    = $cal->title->text;
		$feed->color    = $cal->color->value;
		$feed->url      = $this->fix_url( $cal->id->text );
		$feed->timezone = $cal->timezone->value;

		return $feed;
	}

	private function fix_url( $url )
	{
		$pattern = '/\/default\//';
		$replacement = '/';
		return preg_replace( $pattern, $replacement, $url ) . '/public/full';
	}

	public function test_feed( $feed )
	{
		$this->load_zend_framework();

		$calendar = new Zend_Gdata_Calendar();

		$event_query = $calendar->newEventQuery( $feed->url );
		$event_query->setUser( null );
		$event_query->setVisibility( null );
		$event_query->setProjection( null );

		try
		{
			$event_feed = $calendar->getCalendarEventFeed( $event_query );
		}

		catch ( Exception $e )
		{
			return false;
		}

		return true;		
	}

	/**
	 * Uses SimplePie
	 */
	public function read_events( $feed, $query )
	{
		$this->load_simplepie_gcalendar();
		$gcal = $this->build_simplepie_gcalendar( $feed, $query );

		$events = array();

		foreach ( $gcal->get_items() as $gcal_event )
		{
			$event = $this->build_event( $gcal_event );

			$event->feed = $feed;
			$event->query = $query;

			if ( $event->start_date >= time() )
			{
				$events[] = $event;
			}
		}

		return $events;
	}

	private function build_event( $gcal_event )
	{
		$event = new Flexical_Model_Event();

		$event->id = $gcal_event->get_id();
		$event->title = $gcal_event->get_title();
		$event->description = $gcal_event->get_description();
		$event->location = $gcal_event->get_location();
		$event->start_date = $gcal_event->get_start_date();
		$event->end_date = $gcal_event->get_end_date();

		return $event;
	}

	private function load_simplepie_gcalendar()
	{
		if ( ! class_exists( 'SimplePie' ) )
		{
			require_once( 'simplepie/simplepie.inc' );
		}

		if ( ! class_exists( 'SimplePie_GCalendar' ) )
		{
			require_once( 'simplepie-gcalendar/simplepie-gcalendar.php' );
		}
	}

	private function build_simplepie_gcalendar( $feed, $query )
	{
		$gcal = new SimplePie_GCalendar( $feed->url, $this->cache_location, $this->cache_duration );

		// Use $query properties to set $gcal properties
		$gcal->set_projection( 'full' );
		$gcal->set_show_past_events( FALSE );

		//
		$gcal->set_show_past_events( ! $query->futureevents );

		//
        // $gcal->set_sort_ascending($value = TRUE);

		//
		// $gcal->set_orderby_by_start_date( $query->);

		//
		$gcal->set_expand_single_events( $query->singleevents );

		//
		// $gcal->set_cal_language($value = "");

		//
		// $gcal->set_cal_query($value = "");

		//
		// $gcal->set_start_date($value = 0);

		//
		// $gcal->set_end_date( 0 );

		//
		$gcal->set_timezone( $feed->timezone );

		// Initialize
		$gcal->init();
		$gcal->handle_content_type();

		return $gcal;
	}
}

?>
